home *** CD-ROM | disk | FTP | other *** search
- _USING DPMI TO HOOK INTERRUPTS IN WINDOWS 3_
- by Walter Oney
-
- [LISTING ONE]
-
- #############################################################################
- # MAKE file for INTHOOK example and helper programs.
- # By Walter Oney. Use with Microsoft C 6.0A & MASM 5.1 (or compatibles)
- #############################################################################
-
- all: inthook.exe int60.com int61.com
-
- inthook.obj: inthook.c
- cl -AS -Zlipe -c -Gsw2 -Ows -W3 inthook.c >inthook.err
- inthook.exe: inthook.obj
- link /noe /nod /co /m inthook,inthook,inthook,slibcaw libw,inthook;
- rc inthook.exe
- mapsym inthook
- int60.com: int60.asm
- masm int60;
- link int60;
- exe2bin int60 int60.com
- int61.com: int61.asm
- masm int61;
- link int61;
- exe2bin int61 int61.com
-
-
-
-
- [LISTING TWO]
-
- /****************************************************************************
- * INTHOOK.C -- by Walter Oney Use with Microsoft C 6.0A.
- * Sample app illustrating interrupt hooking in Win3 using DPMI 0.9 services
- ****************************************************************************/
-
- /* Include files */
- #include "windows.h" /* MS windows dcls */
- #include "dos.h" /* for FP_SEG, FP_OFF */
-
- /* Local procedures and data */
- static HANDLE hInst ; /* current instance handle */
- static HWND hMyWindow ; /* handle for our window */
- static void (interrupt far *org60)() ; /* original INT 60 handler */
- static void (far *callback)() ; /* real mode callback address */
- typedef struct
- { /* real mode callback */
- unsigned long edi, esi, ebp, junk, ebx, edx, ecx, eax ;
- unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss ;
- } CBSTRUCT ; /* real mode callback */
- CBSTRUCT cb60 ; /* callback for INT 60 handling */
-
- static void hook60(void) ; /* hook INT 60 */
- static void unhook60(void) ; /* unhook INT 60 */
- static void interrupt far int60() ; /* interrupt handler */
-
- /**********************************************************************/
- /* Main window procedure: */
- LONG FAR PASCAL MainWndProc
- (HWND hWnd, /* window handle */
- WORD iMessage, /* message code */
- WORD wParam, /* 1st parameter */
- LONG lParam) /* 2d parameter */
- { /* MainWndProc */
- /* Local variables */
- long retcode = 0 ; /* return code */
- /* Text */
- switch(iMessage)
- { /* process message */
- case WM_CREATE:
- hMyWindow = hWnd ; /* so INT60 can find it */
- hook60() ;
- break ;
- case WM_USER: /* posted by int60() */
- MessageBox(GetFocus(), "Wake up!", "Salutations",
- MB_ICONEXCLAMATION | MB_OK) ;
- break ;
- case WM_DESTROY: /* window being destroyed */
- unhook60() ;
- PostQuitMessage(0) ;
- break ;
- default: /* some other message */
- retcode = DefWindowProc(hWnd, iMessage, wParam, lParam) ;
- break ;
- } /* process message */
- return retcode ;
- } /* MainWndProc */
-
- /**********************************************************************/
- /* Window message loop: */
- int PASCAL WinMain
- (HANDLE hInstance, /* current instance */
- HANDLE hPrevInstance, /* previous instance (if any) */
- LPSTR lpCmdLine, /* command line */
- int nCmdShow) /* show window type (open/icon) */
- { /* WinMain */
- /* Local variables */
- HWND hWnd ; /* window handle */
- MSG msg ; /* current message */
- WNDCLASS wc ; /* template for this class */
- /* Text */
- /* Only allow one instance of the application at a time -- there's only
- one interrupt vector to hook! */
- if (hPrevInstance)
- return FALSE ;
- /* Create the window class. */
- wc.style = 0 ; /* default styles */
- wc.lpfnWndProc = MainWndProc ; /* window proc */
- wc.cbClsExtra = 0 ; /* no extra bytes for class */
- wc.cbWndExtra = 0 ; /* no extra bytes for instance */
- wc.hInstance = hInstance ; /* who created the class */
- wc.hIcon = LoadIcon(NULL, IDI_APPLICATION) ;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW) ; /* default cursor */
- wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;
- wc.lpszMenuName = NULL ; /* no menu */
- wc.lpszClassName = "AppWClass" ; /* name of window class */
- if (!RegisterClass(&wc))
- return FALSE ;
- /* Create an instance of the class (i.e., our own window) */
- hInst = hInstance ; /* so window proc can access it */
- hWnd = CreateWindow("AppWClass",
- "Interrupt Hook Sample Application",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL, NULL, hInstance, NULL) ;
- if (!hWnd)
- return FALSE ;
- ShowWindow(hWnd, SW_SHOWMINIMIZED) ;
- UpdateWindow(hWnd) ;
- /* Main message loop */
- while (GetMessage(&msg, NULL, NULL, NULL))
- { /* until WM_QUIT message */
- TranslateMessage(&msg) ; /* xlate virtual key codes */
- DispatchMessage(&msg) ; /* dispatch handler */
- } /* until WM_QUIT message */
- return msg.wParam ; /* PostQuitMessage's arg */
- } /* WinMain */
-
- /**********************************************************************/
- /* HOOK60 hooks software interrupt 60h in real mode, using a real-mode
- callback to get control passed to int60(). */
- static void hook60()
- { /* hook60 */
- _asm
- {
- push ds ; save DS across call
-
- mov ax, ds ; ES:DI -> callback structure
- mov es, ax ; ..
- mov di, offset cb60; ..
- mov ax, cs ; DS:SI -> routine to call
- mov ds, ax ; ..
- mov si, offset int60 ; ..
- mov ax, 0303h ; fcn 0303: allocate real mode callback
- int 31h ; issue DPMI function request
-
- pop ds ; restore DS
- mov callback, dx ; CX:DX = callback address
- mov callback+2, cx ; ..
-
- mov bl, 60h ; BL = interrupt number (60h)
- mov ax, 0200h ; fcn 0200: get real mode interrupt vector
- int 31h ; issue DPMI function request
- mov org60, dx ; CX:DX = original real mode vector
- mov org60+2, cx ; ..
-
- mov dx, callback ; CX:DX = new REAL MODE handler address
- mov cx, callback+2 ; ..
- mov ax, 0201h ; fcn 0201: set real mode interrupt vector
- int 31h ; issue DPMI fcn request
- }
- } /* hook60 */
-
- /**********************************************************************/
- /* UNHOOK60 restores the original interrupt 60h vector. */
- static void unhook60()
- { /* unhook60 */
- _asm
- {
- mov dx, org60 ; CX:DX = original INT 60 vector
- mov cx, org60+2 ; ..
- mov bl, 60h ; BL = interrupt number (60h)
- mov ax, 0201h ; fcn 0201: set real mode interrupt vector
- int 31h ; issue DPMI fcn request
-
- mov dx, callback ; CX:DX = real-mode callback address
- mov cx, callback+2 ; ..
- mov ax, 0304h ; fcn 0304: free real mode callback
- int 31h ; issue DPMI fcn request
- }
- } /* unhook60 */
-
- /**********************************************************************/
- /* INT60 is the interrupt handler for interrupt 60h. It gains control from
- the real-mode callback address allocated by HOOK60() and uses PostMessage
- to send a message to the application's window procedure. */
- typedef struct
- { /* interrupt register structure */
- unsigned short es, ds ;
- unsigned short di, si, bp, sp, bx, dx, cx, ax ;
- unsigned short flags, ip, cs ;
- } IFRAME ; /* interrupt register structure */
- static void interrupt far int60(IFRAME f)
- { /* int60 */
- unsigned int far *isp ; /* interrupting stack pointer */
- /* Simulate IRET in signalling process. */
- FP_SEG(isp) = f.ds ;
- FP_OFF(isp) = f.si ;
- cb60.ip = isp[0] ;
- cb60.cs = isp[1] ;
- cb60.flags = isp[2] ;
- cb60.sp += 6 ;
- /* Post a private message leading to a message box. */
- PostMessage(hMyWindow, WM_USER, NULL, NULL) ;
- } /* int60 */
-
-
-
- [LISTING THREE]
-
- NAME INTHOOK
- DESCRIPTION 'Interrupt Hook Sample Application'
- EXETYPE WINDOWS
- STUB 'WINSTUB.EXE'
- CODE PRELOAD MOVEABLE DISCARDABLE
- DATA PRELOAD MOVEABLE MULTIPLE
- HEAPSIZE 1024
- STACKSIZE 5120
- EXPORTS
- MainWndProc @1
-
-
-
- [LISTING FOUR]
-
- ;-----------------------------------------------------------------------------
- ; INT60.ASM -- Signaller program for INTHOOK example app. By Walter Oney.
- ;-----------------------------------------------------------------------------
- name int60
- int60 segment byte public 'code'
- assume cs:int60, ds:int60
- org 100h ; required for .COM file usage
-
- ; See if forwarder program is present by checking interrupt vector for 61h.
- begin: mov ax, 3561h ; get int 61 vector address
- int 21h ; ..
- mov ax, es ; be sure there is one
- or ax, bx ; ..
- jz cantcall ; if not, complain and quit
-
- ; Use 2F/1685 to switch to system virtual machine and call forwarder program.
- ; Note that no-one actually does an INT 61h--we simply use the vector as a
- ; convenient (and facile) place to park the address of the callback
- mov ax, 1685h ; fcn 1685: switch VM's and callback
- mov di, bx ; ES:DI = callback address (int 61 hdlr)
- mov bx, 1 ; BX = VM to switch to (system VM)
- mov cx, 3 ; CX = .... .... .... ..11 -- wait until
- ; interrupts enabled and critical
- ; section unowned
- xor dx, dx ; DX:SI = priority boost (zero)
- xor si, si ; ..
- int 2Fh ; switch to system VM & do INT 60
-
- ; If the forwarder found an INT 60 handler, it saved the address beginning
- ; after a 3-byte JMP located at 100h. Check this in order to complain if
- ; the responder WinApp isn't loaded. Note that this test will sometimes
- ; fail because we're running asynchronously with the system VM.
- mov ax, word ptr es:[103h]; see if forwarder found an INT60 handler
- or ax, word ptr es:[105h]; ..
- jz no60 ; if not, complain about it
- goback: mov ax, 4C00h ; terminate with errorlevel 0
- int 21h ; (does not return)
- cantmsg db 'The forwarder program is not installed', 13, 10, '$'
- nomsg db 'The responder WinApp is not running', 13, 10, '$'
- no60: lea dx, nomsg ; responder not present
- jmp short complain ; ..
- cantcall:lea dx, cantmsg ; forwarder not present
- complain:mov ah, 9 ; fcn 9: print msg in DS:DX on screen
- int 21h ; ..
- jmp goback ; exit
- int60 ends
- end begin
-
-
-
-
- [LISTING FIVE]
-
- ;-----------------------------------------------------------------------------;
- ; INT61.ASM -- Forwarder program for the INTHOOK example application ;
- ; Written by Walter Oney ;
- ;-----------------------------------------------------------------------------;
-
- name int61
- .286p
- int61 segment byte public 'code'
- assume cs:int61, ds:int61
- org 100h ; required for .COM file usage
- begin: jmp doit ; jump around fixed data area
-
- vect60 dw 0, 0 ; for inspection by signaller
-
- doit: mov ax, 2561h ; hook INT 61h so INT60 can find us
- lea dx, callback ; from another virtual machine
- int 21h ; ..
-
- lea dx, endprog+15 ; point past all code in this module
- shr dx, 4 ; compute # paragraphs to keep
- mov ax, 3100h ; terminate and stay resident
- int 21h ; (does not return)
- ; CALLBACK is reached circuitously when INT60 does a 2F/1685 to schedule
- ; it to run in the system virtual machine.
- callback:
- push es ; save working registers
- push ds ; ..
- pusha ; ..
- mov ax, cs ; set DS == CS
- mov ds, ax ; ..
-
- mov ax, 3560h ; get current INT 60 vector address
- int 21h ; ..
- mov vect60, bx ; save for debugging inspection
- mov vect60+2, es ; ..
-
- mov ax, es ; is there a handler?
- or ax, bx ; ..
- jz done60 ; if not, don't signal it!
- int 60h ; issue INT 60 to wakeup WinApp
- done60: popa ; restore registers
- pop ds
- pop es ; ..
- iret ; return from callback to Windows
- endprog: ; for 21/31 paragraph computation
- int61 ends
- end begin
-
-
-
-
- EXAMPLE 1.
-
- pusha
- push ds
- push es
- mov bp,sp
- mov ax,DGROUP
- mov ds,ax
- cld
-
- [function body]
-
- pop es
- pop ds
- popa
- iret
-
-